package edu.hawaii.server;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * This class parses string output from database on TIMELOCATION which contains, time, day, location
 * max class availability and instructor.If string to be parsed is too short split function will 
 * fail. Also if matched no spaces are before or after.
 * 
 * TODO:  
 *  2 - rid of dayTime? and any other un needed methods?
 * 
 * @author brandon
 */
public class TimeLocationParse {

  private String time = "((\\d){4}|(TBA))? to ((\\d){4}|(TBA))?";
  private String loc = "(location)";
  private String mRoom = "(Max Rm. capacity)";
  private String inst = "(Instr: )";

  private int iDayTime, iLocation, iMaxRoom, iInstr;
  private String rawString;
  private String sDayTime, sDay, sTime, sLocation, sMaxRoom, sInstr;

  /**
   * Contructor with raw string parameter, sets class variables and calls method splitUp.
   * 
   * @param rString The raw string that needs prasing.
   */
  public TimeLocationParse(String rString) {

    this.iLocation = 0;
    this.iMaxRoom = 0;
    this.iInstr = 0;
    this.iDayTime = 0;
    this.sDayTime = null;
    this.sDay = null;
    this.sTime = null;
    this.sLocation = null;
    this.sMaxRoom = null;
    this.sInstr = null;

    this.rawString = rString;
    splitUp();
    convertTime();
  }

  /**
   * Constructor with no parameters.
   */
  public TimeLocationParse() {

    this.iLocation = 0;
    this.iMaxRoom = 0;
    this.iInstr = 0;
    this.iDayTime = 0;
    
    this.sDayTime = null;
    this.sDay = null;
    this.sTime = null;
    this.sLocation = null;
    this.sMaxRoom = null;
    this.sInstr = null;
    this.rawString = "";
  }

  /**
   * Sets new string to be parsed, calls splitUp method to spilt it up.
   * 
   * @param rString The new string to parse.
   */
  public void setRawString(String rString) {
    
    this.rawString = rString;
    
    this.sDayTime = null;
    this.sDay = null;
    this.sTime = null;
    this.sLocation = null;
    this.sMaxRoom = null;
    this.sInstr = null;
    
    this.iLocation = 0;
    this.iMaxRoom = 0;
    this.iInstr = 0;
    this.iDayTime = 0;
    splitUp();
    convertTime();
  }
  
  /**
   * Returns the raw string to be parsed. For testing purposes
   * 
   * @return rawString The new string to parse.
   */
  public String getRawString() {
    return this.rawString;
  }

  /**
   * Method parses rawString, into location, day and time, instructor and max room capacity.
   * 
   * @throws StringIndexOutOfBoundsException if raw string to parse is too short, didn't come from 
   * the database.
   */
  public void splitUp() throws StringIndexOutOfBoundsException {

    int start = 0;
    Matcher m;
    
    // -------------------------seperate time
    
    m = setMatcher(time);
    while (m.find()) {
        this.sTime = m.group();
        
        if (m.start() >= 1) {
          start = m.start() - 1;
        }
        else {
          start = 0;
        }
    }
    if (this.sTime == null) {
      // probably TBA so probably no match
    }
    this.sDay = this.rawString.substring(0, start);

    // -------------------------seperate Days and time
    m = setMatcher(loc);
    while (m.find()) {
      start = m.start();
      this.iLocation = m.end() + 1;
    }
    this.sDayTime = this.rawString.substring(0, start);
    m = setMatcher(mRoom); // -------------------------seperate location, max room
    while (m.find()) {
      start = m.start() - 2;
      this.iMaxRoom = m.end() + 1;
    }
    this.sLocation = this.rawString.substring(this.iLocation, start);

    // -------------------------seperate instructor
    m = setMatcher(inst);
    while (m.find()) {
      start = m.start() - 3;
      this.iInstr = m.end();
    }
    this.sMaxRoom = this.rawString.substring(this.iMaxRoom, start);
    this.sInstr = this.rawString.substring(this.iInstr, this.rawString.length() - 1);
    
  }
  
  /**
   * Takes string sTime and converts from military to am pm.
   * 
   */
  private void convertTime() {
    
    String temp1 = this.sTime;
    String temp2,temp3 = null;
    
   
    if (!temp1.equals("TBA to TBA")) {  //do something only if not TBA
      
      Pattern loc = Pattern.compile("(\\d){4}");
      Matcher m = loc.matcher(temp1);
      
      while (m.find()) {
        int itemp = Integer.valueOf(m.group());
        
        if (itemp < 1200) {
          temp2 = itemp + " am";
        }
        else {
          if (itemp >= 1200 && itemp < 1300) {
            temp2 = itemp + " pm";
          }
          else {
            temp2 = (itemp - 1200) + " pm";
          }
        }
        if (temp3 == null) {
          
          temp3 = temp2;
        }
        else {
          temp3 = temp3 + "-" + temp2;
        }
      } //end while
      this.sTime = temp3;
    } //end if
  }
  /**
   * Sets the matching pattern. For inturnal use in split up.
   * 
   * @param pattern The new pattern to match against.
   * @return Matcher with the new pattern
   */
  private Matcher setMatcher(String pattern) {

    Pattern loc = Pattern.compile(pattern);
    Matcher m = loc.matcher(this.rawString);

    return m;
  }
 

  /**
   * Returns the parsed location or an empty string.
   * 
   * @return sLocation The class location if present.
   */
  public String getLocation() {

    return this.sLocation;
  }

  /**
   * Returns the time and day of class or an empty string.
   * 
   * @return sLocation The string containing class time and day(s).
   */
  public String getDayTime() {

    return this.sDayTime;
  }

  /**
   * Returns Max room Capacity or empty string.
   * 
   * @return sMaxRoom the string containing the max number of students for that class.
   */
  public String getMaxRoomCap() {

    return this.sMaxRoom;
  }

  /**
   * Returns the instructor of class or empty string.
   * 
   * @return sInstr The string containing the instructor of the class.
   */
  public String getInstructor() {

    return this.sInstr;
  }

  /**
   * Returns the Time of class or empty string. If case "TBA to TBA" that will be returned.
   * 
   * @return sTime The string containing the time of the class.
   */
  public String getTime() {

    return this.sTime;
  }

  /**
   * Returns the Days of class or empty string.
   * 
   * @return sDay The string containing the day(s) of the class.
   */
  public String getDay() {

    return this.sDay;
  }

  /**
   * Used for testing purposes to see the contents of class variables. Prints out day, location and
   * max room capacity.
   */
  public void printVariables() {
    System.out.print("\n\t day time start: " + this.iDayTime + "\n\t location start: "
        + this.iLocation + "\n\t Max Capacity: " + this.iMaxRoom);
  }

}
